package com.pajk.user.service.admin;

import com.pajk.user.ExceptionCode;
import com.pajk.user.api.UserAdminService;
import com.pajk.user.api.UserService;
import com.pajk.user.dal.index.Index;
import com.pajk.user.dal.mapper.AccountChannelMapper;
import com.pajk.user.dal.mapper.AdminMapper;
import com.pajk.user.dal.mapper.UserRelationMapper;
import com.pajk.user.dal.model.AccountChannelDO;
import com.pajk.user.exception.UserServiceException;
import com.pajk.user.model.InviteInfo;
import com.pajk.user.model.User;
import com.pajk.user.model.UserRelation;
import com.pajk.user.model.enums.ChannelType;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;

/**
 * Created by peide.zhang on 2014/6/7.
 */
public class UserAdminServiceImpl implements UserAdminService {

    private static final Logger Log = LoggerFactory.getLogger(UserAdminServiceImpl.class);

    @Resource
    Index<String, Long> weixinOpenIdToUserIdIndex;

    @Resource
    Index<Long, Long> mobileToUserIdIndex;

    @Resource
    Index<String, Long> wanliToUserIdIndex;

    @Resource
    Index<String,InviteInfo> inviteeMobileToInviteInfoIndex;

    @Resource
    Index<Long,List<String>> inviteListIndex;

    @Resource
    AdminMapper adminMapper;

    @Resource
    UserService userService;

    @Resource
    UserRelationMapper userRelationMapper;

    @Resource
    AccountChannelMapper accountChannelMapper;

    @Override
    public void delUserInfoByOpenId(String openId, ChannelType from) {
        if ((openId == null) || (from == null)) {
            throw new IllegalArgumentException(String.format("input parameter cannot be null! openId = %s, from = %s", openId, from));
        }
        if (from != ChannelType.WEIXIN) {
            throw new IllegalArgumentException(String.format("Only WEIXIN channel type is supported for now! ChannelType received = %s", from));
        }

        if (openId.length() > 64) {
            throw new IllegalArgumentException("Open ID length exceeded 64 chars!");
        }

        Log.info("delUserInfoByOpenId {}", openId);
        Long userId = weixinOpenIdToUserIdIndex.get(openId);
        if(userId!=null){
            delUserInfo(userId);
            weixinOpenIdToUserIdIndex.remove(openId);
        }
        Log.info("delUserInfoByOpenId done {}",openId);
    }


    @Override
    public void delUserInfoByUserId(Long userId) {
        if ((userId == null)) {
            throw new IllegalArgumentException(String.format("userId cannot be null"));
        }

        Log.info("delUserInfoByUserId {}",userId);
        delUserInfo(userId);
        Log.info("delUserInfoByUserId done {}",userId);
    }

    @Override
    public void delUserInfoByMobile(Long mobile) {
        if ((mobile == null)) {
            throw new IllegalArgumentException(String.format("mobile cannot be null"));
        }
        Log.info("delUserInfoByMobile {}",mobile);
        Long userId=mobileToUserIdIndex.get(mobile);
        if(userId!=null){
            delUserInfo(userId);
            mobileToUserIdIndex.remove(mobile);
        }
        Log.info("delUserInfoByMobile done {}",mobile);
    }

    public void delUserInfo(long userId){
        try{
            User user =userService.getUserById(userId);
            if(user!=null){
                delTair(user);
            }
            delDBData(userId);
        } catch (Throwable t) {
            Log.error("unknown exception catched!", t);
            throw new UserServiceException(t, ExceptionCode.InternalSystemErrorException.getCode());
        }

    }

    public void delTair(User user){
        //wanli
        String wanliId=user.getWanliId();
        if(!StringUtils.isEmpty(wanliId)){
            Long wanliReverseUserId=wanliToUserIdIndex.get(wanliId);
            if(wanliReverseUserId!=null && wanliReverseUserId.equals(user.getId())){
                wanliToUserIdIndex.remove(wanliId);
            }
        }

        //openId
        List<AccountChannelDO> AccountChannelList = accountChannelMapper.getAccountChannelByUserId(user.getId());
        for (AccountChannelDO accountChannelDO : AccountChannelList) {
            if(accountChannelDO.getFrom().equals(ChannelType.WEIXIN)){
                weixinOpenIdToUserIdIndex.remove(accountChannelDO.getOpenId());
            }
        }

        //mobile
        Long mobile=user.getMobile();
        if(mobile!=null){
            Long reverseUserId=mobileToUserIdIndex.get(mobile);
                if (reverseUserId!=null && reverseUserId.longValue() != user.getId()) {
                    throw new UserServiceException(String.format("mobile(%d) bind another used by User(%d)!", mobile, reverseUserId),
                            ExceptionCode.StaleDataException.getCode());
                }else{
                    mobileToUserIdIndex.remove(mobile);
                }
            }

        //用户邀请信息
        List<String> inviteList=inviteListIndex.get(user.getId());
        if(inviteList!=null && inviteList.size()>0){
            for (String inviteeMobile : inviteList) {
                inviteeMobileToInviteInfoIndex.remove(inviteeMobile);
            }
            inviteListIndex.remove(user.getId());
        }
    }

    public void delDBData(Long userId){
        StringBuffer dbInfo=new StringBuffer();
        int accountChannelCount=adminMapper.deleteAccountChannel(userId);
        int userExtCount=adminMapper.deleteUserExt(userId);
        int creditHisCount=adminMapper.deleteCreditHis(userId);
        int userDeviceBindingCount=adminMapper.deleteUserDeviceBinding(userId);

        List<UserRelation> followeeList=  userService.getFollowees(userId);
        for (UserRelation userRelation : followeeList) {
            dbInfo.append("reverseRelation:");
            int reverseRelationCount=adminMapper.deleteUserReverseRelation(userRelation.getFollowerId(),userRelation.getFolloweeId());
            if(reverseRelationCount>=0){
                dbInfo.append(userRelation.getFollowerId()+" "+userRelation.getFolloweeId()).append("\n");
            }
        }
        int userRelationCount=adminMapper.deleteUserRelation(userId);

        adminMapper.deleteUser(userId);

        dbInfo.append("accountChannelCount=").append(accountChannelCount).append("\n");
        dbInfo.append("userExtCount=").append(userExtCount).append("\n");
        dbInfo.append("creditHisCount=").append(creditHisCount).append("\n");
        dbInfo.append("userDeviceBindingCount=").append(userDeviceBindingCount).append("\n");
        dbInfo.append("userRelationCount=").append(userRelationCount).append("\n");
        Log.info("\nuserId {} delDBData \n{}",userId,dbInfo);
    }

}
